﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace RegionSplittor.Utils
{
	public class WallCreator
	{
		public static List<KeyValuePair<ElementId, ElementId>> CreateCurveWalls(Autodesk.Revit.DB.Document doc, List<Element> arBeam, Level level)
		{
			List<KeyValuePair<ElementId, ElementId>> list = new List<KeyValuePair<ElementId, ElementId>>();
			if (level == null)
			{
				return list;
			}
			ElementId id = level.Id;
			WallType baseWallType = WallCreator.GetBaseWallType(doc);
			foreach (Element element in arBeam)
			{
				try
				{
					double num = 0.0;
					double num2 = 0.0;
					Curve curve = null;
					if (element is FamilyInstance)
					{
						FamilyInstance famIns = element as FamilyInstance;
						Element beamType = WallCreator.GetBeamType(doc, famIns);
						num = WallCreator.GetBeamWidth(beamType);
						num2 = WallCreator.GetBeamHeight(beamType);
						curve = WallCreator.GetBeamCurve(famIns);
					}
					else if (element is Wall)
					{
						Wall wall = element as Wall;
						num = wall.Width;
						num2 = WallCreator.GetWallNotConnectHeight(wall);
					}
					if (0.0 != num && 0.0 != num2)
					{
						WallType wallType = WallCreator.CreateWidthWallType(doc, baseWallType, num);
						if (wallType != null)
						{
							if (!(null == curve))
							{
								Transaction transaction = new Transaction(doc);
								transaction.Start("new wall");
								try
								{
									Wall wall2 = Wall.Create(doc, curve, wallType.Id, id, num2, 0.0, false, false);
									wall2.get_Parameter(BuiltInParameter.WALL_ATTR_ROOM_BOUNDING).Set(1);
									transaction.Commit();
									list.Add(new KeyValuePair<ElementId, ElementId>(wall2.Id, element.Id));
								}
								catch
								{
									transaction.RollBack();
								}
							}
						}
					}
				}
				catch
				{
				}
			}
			return list;
		}

		public static List<ElementId> GetAllNoConnectWalls(List<Element> arEle, Autodesk.Revit.DB.Document doc)
		{
			List<ElementId> list = new List<ElementId>();
			Transaction transaction = new Transaction(doc);
			transaction.Start("modify wall attribute");
			try
			{
				foreach (Element element in arEle)
				{
					if (element is Wall)
					{
						try
						{
							(element as Wall).get_Parameter(BuiltInParameter.WALL_ATTR_ROOM_BOUNDING).Set(1);
						}
						catch
						{
							continue;
						}
						list.Add(element.Id);
					}
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
			return list;
		}

		private static WallType GetBaseWallType(Autodesk.Revit.DB.Document doc)
		{
			List<WallType> list = new List<WallType>();
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(WallType)).ToElements())
			{
				WallType wallType = element as WallType;
				if (wallType.Kind == null)
				{
					list.Add(wallType);
				}
			}
			return list.First<WallType>();
		}

		private static WallType GetBaseWallType(Autodesk.Revit.DB.Document doc, string strTypeName)
		{
			WallType result = null;
			new List<WallType>();
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(WallType)).ToElements())
			{
				WallType wallType = element as WallType;
				if (wallType.Name == strTypeName)
				{
					result = wallType;
					break;
				}
			}
			return result;
		}

		private static WallType CreateWidthWallType(Autodesk.Revit.DB.Document doc, WallType oldType, double dWidth)
		{
			WallType wallType = null;
			int num = 0;
			string text = oldType.Name + "Temp" + dWidth.ToString("f0");
			wallType = WallCreator.GetBaseWallType(doc, text);
			if (wallType != null)
			{
				return wallType;
			}
			string text2 = oldType.Name + "Temp" + dWidth.ToString("f0");
			Transaction transaction = new Transaction(doc);
			transaction.Start("new wall type");
			for (;;)
			{
				try
				{
					wallType = (oldType.Duplicate(text) as WallType);
				}
				catch
				{
					num++;
					text2 += num.ToString();
					text = text2;
					continue;
				}
				break;
			}
			if (wallType != null)
			{
				double width = wallType.Width;
				if (Math.Abs(Math.Abs(dWidth - width) - 0.0) >= 1E-06)
				{
                    CompoundStructure compoundStructure = CompoundStructure.CreateSingleLayerCompoundStructure((MaterialFunctionAssignment)1, dWidth, ElementId.InvalidElementId);
					wallType.SetCompoundStructure(compoundStructure);
				}
			}
			transaction.Commit();
			return wallType;
		}

		private static double GetBeamWidth(Element beamType)
		{
			double result = 0.0;
			if (beamType == null)
			{
				return result;
			}
			try
			{
				result = beamType.GetParameter("b").AsDouble();
			}
			catch
			{
			}
			return result;
		}

		private static double GetBeamHeight(Element beamType)
		{
			double result = 0.0;
			if (beamType == null)
			{
				return result;
			}
			try
			{
				result = beamType.GetParameter("h").AsDouble();
			}
			catch
			{
			}
			return result;
		}

		private static Element GetBeamType(Autodesk.Revit.DB.Document doc, FamilyInstance famIns)
		{
			return doc.GetElement(famIns.GetTypeId());
		}

		private static Curve GetBeamCurve(FamilyInstance famIns)
		{
			Curve result = null;
			LocationCurve locationCurve = famIns.Location as LocationCurve;
			if (locationCurve != null)
			{
				result = locationCurve.Curve;
			}
			return result;
		}

		private static double GetWallNotConnectHeight(Wall wall)
		{
			return wall.GetParameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).AsDouble();
		}

		private static List<ElementId> GetPriBeamIntersectWalls(FamilyInstance famIns)
		{
			List<ElementId> list = new List<ElementId>();
			if (famIns == null)
			{
				return list;
			}
			foreach (GeometryObject geometryObject in famIns.get_Geometry(new Options()))
			{
				Solid solid = geometryObject as Solid;
				if (solid != null)
				{
					FilteredElementCollector filteredElementCollector = new FilteredElementCollector(famIns.Document);
					filteredElementCollector.OfClass(typeof(Wall));
					ElementIntersectsSolidFilter elementIntersectsSolidFilter = new ElementIntersectsSolidFilter(solid);
					List<ElementId> list2 = filteredElementCollector.WherePasses(elementIntersectsSolidFilter).ToElementIds().ToList<ElementId>();
					if (list2.Count > 0)
					{
						list.AddRange(list2.Distinct<ElementId>());
					}
				}
			}
			return list;
		}
	}
}
